create or replace function pgds_gen_bytea(len int) returns bytea as $$
declare message bytea;
declare i int;
begin
        i := 0;
        message := '';
        loop
                message := message || ' ';
                message := set_byte(message, i, (0 + (random()*255)::int));
                i := i + 1;
                if i >= len then
                        exit;
                end if;
        end loop;
	return message;
end;
$$ language plpgsql;

create or replace function pgds_test_rsa(nbits int, len1 int, len2 int) returns int as $$
declare message bytea;
declare enc_message bytea;
declare dec_message bytea;
declare private_key text;
declare public_key text;
declare r record;
begin
        private_key := gen_keys_pair('rsa', nbits);
        if private_key = '' then
                return 1;
        end if;
        public_key := get_public_key(private_key);
        if public_key = '' then
                return 2;
        end if;
        message := pgds_gen_bytea(len1);
        enc_message := rsa_private_encrypt(private_key, message);
        if enc_message = '' then
                return 3;
        end if;
        if enc_message = message then
                return 4;
        end if;
        dec_message := rsa_public_decrypt(public_key, enc_message);
	if dec_message = '' then
		return 5;
	end if;
        if dec_message <> message then
                return 6;
        end if;
        enc_message := rsa_public_encrypt(public_key, message);
        if enc_message = '' then
                return 7;
        end if;
        if enc_message = message then
                return 8;
        end if;
        dec_message := rsa_private_decrypt(private_key, enc_message);
        if dec_message <> message then
                return 9;
        end if;
        for r in select alg from regexp_split_to_table('rsa/md2 rsa/md4 rsa/md5 rsa/sha1 rsa/sha224 rsa/sha256 rsa/sha384 rsa/sha512', E'\\s+') as alg loop
		if nbits <= 512 and r.alg in ('rsa/sha512', 'rsa/sha384') then
			--raise notice 'message digest to large (%)', r.alg;
		else
			message := pgds_gen_bytea(len2);
			enc_message := sign(r.alg, private_key, message);
			if enc_message = '' then
				return 10;
			end if;
			if enc_message = message then
				return 11;
			end if;
			if verify(r.alg, public_key, message, enc_message) <> 1 then
				return 12;
			end if;
		end if;
        end loop;
        return 0;
end;
$$ language plpgsql;


select * from (

      select 1 as test, pgds_test_rsa(512, 16, 512) as rc
union select 2 as test, pgds_test_rsa(512, 32, 1024) as rc
union select 3 as test, pgds_test_rsa(512, 48, 2048) as rc
union select 4 as test, pgds_test_rsa(512, 51, 4096) as rc
union select 5 as test, pgds_test_rsa(512, 53, 8192) as rc

union select 6 as test, pgds_test_rsa(1024, 8, 1024) as rc
union select 7 as test, pgds_test_rsa(1024, 16, 1024) as rc
union select 8 as test, pgds_test_rsa(1024, 32, 2048) as rc
union select 9 as test, pgds_test_rsa(1024, 64, 4096) as rc
union select 10 as test, pgds_test_rsa(1024, 96, 8192) as rc
union select 11 as test, pgds_test_rsa(1024, 117, 8192) as rc

union select 12 as test, pgds_test_rsa(2048, 32, 1024) as rc
union select 13 as test, pgds_test_rsa(2048, 64, 1024) as rc
union select 14 as test, pgds_test_rsa(2048, 128, 2048) as rc
union select 15 as test, pgds_test_rsa(2048, 192, 4096) as rc
union select 16 as test, pgds_test_rsa(2048, 200, 8192) as rc
union select 17 as test, pgds_test_rsa(2048, 224, 16384) as rc
union select 18 as test, pgds_test_rsa(2048, 245, 32768) as rc

union select 19 as test, pgds_test_rsa(4096, 202, 1024) as rc
union select 20 as test, pgds_test_rsa(4096, 256, 1024) as rc
union select 21 as test, pgds_test_rsa(4096, 224, 2048) as rc
union select 22 as test, pgds_test_rsa(4096, 287, 4096) as rc
union select 23 as test, pgds_test_rsa(4096, 356, 8192) as rc
union select 24 as test, pgds_test_rsa(4096, 386, 16384) as rc
union select 25 as test, pgds_test_rsa(4096, 486, 32768) as rc
union select 25 as test, pgds_test_rsa(4096, 501, 65536) as rc

) s1 order by s1.test
;

drop function pgds_gen_bytea(len int);
drop function pgds_test_rsa(nbits int, len1 int, len2 int);

